package com.jd.rapid.rpc.client.proxy;

import com.jd.rapid.rpc.client.RpcClientHandler;
import com.jd.rapid.rpc.client.RpcConnectManager;
import com.jd.rapid.rpc.client.RpcFuture;
import com.jd.rapid.rpc.codec.RpcRequest;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.TimeUnit;


/**
 * 代理实现类
 * @param <T>
 */
public class RpcProxyImpl<T> implements InvocationHandler,RpcAsyncProxy {

    private Class<T> interfaceClass;
    private long timeout;

    public RpcProxyImpl(Class<T> interfaceClass,long timeout){
            this.interfaceClass=interfaceClass;
            this.timeout=timeout;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //1、设置请求对象
        RpcRequest request=new RpcRequest();
        request.setRequestId(UUID.randomUUID().toString());
        request.setClassName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParamterType(method.getParameterTypes());
        request.setParamters(args);
        //2、选择一个合适的Client任务处理器
        RpcClientHandler rpcClientHandler=RpcConnectManager.getInstance().chooseHandler();
        //3、发送真正的客户端请求返回结果
        RpcFuture rpcFuture=rpcClientHandler.sendRequest(request);
        return rpcFuture.get(timeout, TimeUnit.SECONDS);
    }


    /**
     * 异步的代理接口实现，真正的抛出去RpcFuture给业务方法做实际的回调等待处理
     * @param funcName
     * @param args
     * @return
     */
    @Override
    public RpcFuture call(String funcName, Object... args) {
        //1、设置请求对象
        RpcRequest request=new RpcRequest();
        request.setRequestId(UUID.randomUUID().toString());
        request.setClassName(this.interfaceClass.getName());
        request.setMethodName(funcName);
        request.setParamters(args);
        //TODO 不建议这样做，参数出错就推错了,对应的方法参数类型，通过类类型+方法名称+通过反射得到parameterTypes
        //通过interfaceClass 类，知道方法名 -->  找到具体的方法-->拿到方法的参数列表
        Class<?>[] parameterTypes=new Class[args.length];
        for(int i=0;i<args.length;i++){
                parameterTypes[i]=getClassType(args[i]);
        }
        request.setParamterType(parameterTypes);
        //2、选择一个合适的Client任务处理器
        RpcClientHandler rpcClientHandler=RpcConnectManager.getInstance().chooseHandler();
        //3、发送真正的客户端请求返回结果
        RpcFuture rpcFuture=rpcClientHandler.sendRequest(request);
        return rpcFuture;
    }

    private Class<?> getClassType(Object obj){
        Class<?> classType=obj.getClass();
        String typeName=classType.getName();
        if(typeName.equals("java.lang.Integer")){
            return Integer.TYPE;
        }else  if(typeName.equals("java.lang.Long")){
            return Long.TYPE;
        }else  if(typeName.equals("java.lang.Float")){
            return Float.TYPE;
        }else  if(typeName.equals("java.lang.Double")){
            return Double.TYPE;
        }else  if(typeName.equals("java.lang.Character")){
            return Character.TYPE;
        }else  if(typeName.equals("java.lang.Boolean")){
            return Boolean.TYPE;
        }else  if(typeName.equals("java.lang.Short")){
            return Short.TYPE;
        }else  if(typeName.equals("java.lang.Byte")){
            return Byte.TYPE;
        }
        return classType;
    }
}
